package com.example.lcpractice.lc;

import java.util.*;

/**
 * 240. 搜索二维矩阵 II
 * 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性：
 * <p>
 * 每行的元素从左到右升序排列。
 * 每列的元素从上到下升序排列。
 * <p>
 * <p>
 * 示例 1：
 * <p>
 * <p>
 * 输入：matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5
 * 输出：true
 * 示例 2：
 * <p>
 * <p>
 * 输入：matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 20
 * 输出：false
 * <p>
 * <p>
 * 提示：
 * <p>
 * m == matrix.length
 * n == matrix[i].length
 * 1 <= n, m <= 300
 * -109 <= matrix[i][j] <= 109
 * 每行的所有元素从左到右升序排列
 * 每列的所有元素从上到下升序排列
 * -109 <= target <= 109
 */
public class Lc240 {


    public static void main(String[] args) {
//        System.out.println(Math.floor(Math.sqrt(99))==9);

        int[][] ints = {{-1, 1}};
        System.out.println(searchMatrix(ints, 1));
    }


    public static boolean searchMatrix(int[][] matrix, int target) {
        for (int[] ints : matrix) {
            if (biSearch(ints, target)) {
                return true;
            }
        }
        return false;
    }

    private static boolean biSearch(int[] matrix, int target) {
        int left = 0, right = matrix.length - 1, mid = (left + right) / 2;
        // 注意（left<right）这个条件，防止比如 left=4 ,right=5取中点mid=4最后死循环
        // 而 (left + 1 < right) 这个条件， 在left=4 ,right=5时会直接跳出循环
        while (left + 1 < right) {
            if (matrix[mid] == target) {
                return true;
            } else if (matrix[mid] < target) {
                left = mid;
            } else {
                right = mid;
            }
            mid = (left + right) / 2;
        }
        //比如[[0,1]]中找 0 或 1
        return matrix[left] == target || matrix[right] == target;
    }

    /**
     * 我们可以从矩阵 matrix 的右上角 (0,n−1) 进行搜索。
     * 在每一步的搜索过程中，如果我们位于位置 (x,y)，那么我们希望在以 matrix 的左下角为左下角、以 (x,y) 为右上角的矩阵中进行搜索，
     * 即行的范围为 [x,m−1]，列的范围为 [0,y]：
     * <p>
     * <p>
     * 如果 matrix[x,y]=target，说明搜索完成；
     * <p>
     * 如果 matrix[x,y]>target，由于每一列的元素都是升序排列的，那么在当前的搜索矩阵中，所有位于第 y 列的元素都是严格大于 target 的，
     * 因此我们可以将它们全部忽略，即将 y 减少 1；
     * <p>
     * 如果 matrix[x,y]<target，由于每一行的元素都是升序排列的，那么在当前的搜索矩阵中，所有位于第 x 行的元素都是严格小于 target 的，
     * 因此我们可以将它们全部忽略，即将 x 增加 1。
     * <p>
     * 在搜索的过程中，如果我们超出了矩阵的边界，那么说明矩阵中不存在 target。
     *
     * @param matrix
     * @param target
     * @return
     */
    public boolean searchMatrix2(int[][] matrix, int target) {
        //行数
        int m = matrix.length;
        //列数
        int n = matrix[0].length;
        //从第一行末尾列 开始
        int x = 0, y = n - 1;
        while (x < m && y >= 0) {

            if (matrix[x][y] == target) {
                return true;
            }
            // 如果当前数字小于于末尾 列数递减
            if (matrix[x][y] > target) {
                --y;
                //大于末尾，行数加
            } else {
                ++x;
            }
        }
        return false;
    }

}
